// Copyright (c) 2023 CHANGLEI. All rights reserved.

part of 'arith.dart';

/// Created by changlei on 2023/6/7.
///
/// 表达式
final class Expression with Iterable<Factor>, Describable implements Arith, Argument {
  /// 表达式
  const Expression(this._factors);

  final Iterable<Factor> _factors;

  @override
  Iterator<Factor> get iterator => _factors.iterator;

  /// 计算
  num call([Map<String, ValueGetter<num>>? variables]) {
    return RPN(this).call(variables);
  }

  @override
  String toDescribe([bool isTight = false, Map<String, ValueGetter<num>>? variables]) {
    final iterator = this.iterator;
    if (!iterator.moveNext()) {
      return '';
    }

    String toDescribe(Factor factor) {
      switch (factor) {
        case Variables():
          return factor.toDescribe(isTight, variables);
        case Symbols():
          return factor.toDescribe(isTight);
      }
    }

    final first = toDescribe(iterator.current);
    if (!iterator.moveNext()) {
      return first;
    }
    final buffer = StringBuffer(first);
    do {
      buffer.write(toDescribe(iterator.current));
    } while (iterator.moveNext());
    return buffer.toString();
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other is! Expression || runtimeType != other.runtimeType || length != other.length) {
      return false;
    }
    for (final (index, e) in _factors.indexed) {
      if (e != other.elementAt(index)) {
        return false;
      }
    }
    return true;
  }

  @override
  int get hashCode => Object.hashAll(_factors);
}
